<?php
/**
 * Created by PhpStorm.
 * User: longli
 * VX: isa1589518286
 * Date: 2020/2/20
 * Time: 17:51
 * @link http://www.lmterp.cn
 */

namespace app\common\service\platform;

use app\common\model\AccountSyncLog;
use app\common\model\Orders;
use app\common\model\OrdersTemp;
use app\common\service\export\Order;
use app\common\service\orders\OrderService;
use DateTime;
use Exception;
use MCS\MWSClient;
use think\facade\Log;

/**
 * 亚马逊接口服务
 * Class AmazonService
 * @package app\common\service\amazon
 * @link http://docs.developer.amazonservices.com/zh_CN/orders/2013-09-01/Orders_ListOrders.html
 */
class AmazonService extends BasePlatformService
{
    // tilleuls/amazon-mws-orders  旧包地址
    public static $tokenField = [
        'required' => [ // 必填字段
            [
                'type' => 'text',
                'name' => 'seller_id',
                'field' => 'seller_id',
            ],
            [
                'type' => 'text',
                'name' => 'access_key_id',
                'field' => 'access_key_id',
            ],
            [
                'type' => 'text',
                'name' => 'secret_access_key',
                'field' => 'secret_access_key',
            ],
            [
                'type' => 'select',
                'name' => 'marketplace_id',
                'field' => 'marketplace_id',
                'value' => [
                    'A2EUQ1WTGCTBG2' => 'A2EUQ1WTGCTBG2',
                    'ATVPDKIKX0DER' => 'ATVPDKIKX0DER',
                    'A1AM78C64UM0Y8' => 'A1AM78C64UM0Y8',
                    'A1PA6795UKMFR9' => 'A1PA6795UKMFR9',
                    'A1RKKUPIHCS9HS' => 'A1RKKUPIHCS9HS',
                    'A13V1IB3VIYZZH' => 'A13V1IB3VIYZZH',
                    'A21TJRUUN4KGV' => 'A21TJRUUN4KGV',
                    'APJ6JRA9NG5V4' => 'APJ6JRA9NG5V4',
                    'A1F83G8C2ARO7P' => 'A1F83G8C2ARO7P',
                    'A1VC38T7YXB528' => 'A1VC38T7YXB528',
                    //'AAHKV2X7AFYLW' => 'AAHKV2X7AFYLW',
                    'A39IBJ37TRP1C6' => 'A39IBJ37TRP1C6',
                    'A2Q3Y263D00KWC' => 'A2Q3Y263D00KWC'
                ]
            ],
        ],
        'option' => [ // 可选字段
            [
                'type' => 'text',
                'name' => 'MWSAuthToken',
                'field' => 'MWSAuthToken',
            ],
            [
                'type' => 'text',
                'name' => 'IOSS CODE',
                'field' => 'ioss_code',
            ],
        ],
    ];

    /**
     * amazon 客户端实例
     * @var MWSClient[]
     */
    private static $clientInstance = [];

    /**
     * 获取订单列表
     * @param array $params 参数配置，默认抓取当天订单
     * <ul>
     * <li>string date 要抓取的时间，默认为今天</li>
     * <li>string[] status 要抓取的订单状态，默认['Unshipped', 'PartiallyShipped']</li>
     * <li>string channel 要抓取的订单类型，默认MFN</li>
     * </ul>
     * @param bool $replace 是否替换原有的订单，默认不替换
     * @return array
     * @date 2020/02/20
     * @author longli
     */
    public function getOrderList($params = [], $replace = false)
    {
        Log::info(sprintf("Amazon 批量同步账号【%d】订单，请求参数: 【%s】", $this->getAccountId(), json_encode($params)));
        // 获取客户端
        $client = $this->getClient();
        // 拼接参数
        $dataTime = null;
        try
        {
            $dataTime = new DateTime(empty($params['date']) ? date('Y-m-d') : $params['date']);
        }
        catch(Exception $e){}
        $args = [
            $dataTime, false,
            ['Unshipped', 'PartiallyShipped'],
            'MFN'
        ];
        if(!empty($params['status'])) $args[2] = $params['status'];
        if(!empty($params['channel'])) $args[3] = $params['channel'];

        $nextToken = null; // 初始化下一页订单
        $startSyncTime = time(); // 开始同步时间
        do
        {
            try
            {
                $result = empty($nextToken)
                    ? call_user_func_array([$client, 'ListOrders'], $args) // 获取第一页订单
                    : $client->ListOrdersByNextToken($nextToken); // 获取下一页订单
                // 是否还有下一页
                if(!empty($result['NextToken']))
                {
                    $orderList = isset($result['ListOrders'][0])
                        ? $result['ListOrders']
                        : [$result['ListOrders']];
                    $nextToken = $result['NextToken'];
                }
                else
                {
                    $orderList = $result;
                    $nextToken = null;
                }
                foreach($orderList as $order)
                {
                    $order['order_detail'] = $client->ListOrderItems($order['AmazonOrderId']); // 获取订单详情
                    $this->pushOrderToTemp($order['AmazonOrderId'], $order, $replace);
                }
                sleep(1); // 睡眠 1 秒亚马逊接口限制请求次数
            }catch(Exception $e)
            {
                Log::info(sprintf("Amazon 账号【%d】同步订单，异常信息:【%s】", $this->getAccountId(), $e->getMessage()));
                break;
            }
        }while(!empty($nextToken));
        // 添加同步订单日志
        AccountSyncLog::addLog($this->getAccountId(), $startSyncTime, time(), $args);
    }

    /**
     * 通过订单号获取订单
     * @param string $orderSn 亚马逊订单号
     * @param bool $replace 是否替换原有的订单，默认不替换
     * @return array
     * @date 2020/02/20
     * @author longli
     */
    public function getOrderBySn($orderSn, $replace = false)
    {
        Log::info(sprintf("Amazon 账号【%d】, 通过平台订单号: 【%s】 下载订单", $this->getAccountId(), $orderSn));
        $order = $this->getClient()->GetOrder($orderSn);
        $order['order_detail'] = $this->getOrderDetail($orderSn);
        $this->pushOrderToTemp($order['AmazonOrderId'], $order, $replace);
        return $order;
    }

    /**
     * 获取单个订单详情
     * @param string $orderSn 亚马逊订单号
     * @return array
     * @date 2020/02/20
     * @author longli
     */
    public function getOrderDetail($orderSn)
    {
        return $this->getClient()->ListOrderItems($orderSn);
    }

    public function syncOrder(OrdersTemp $ordersTemp)
    {
        $data = $ordersTemp->order_info;
        $info = [];
        $invoiceCategory = $invoiceTitle = $invoiceDetail = '';
        $account = $this->getAccount();
        $site = $account->site ? explode(',', $account->site)[0] : '';
        foreach($data['order_detail'] as $item)
        {
            $info[] = [
                "item_id"       => $item['OrderItemId'], // 商品 id
                "product_code"  => $item['ASIN'], // 商品编码
                "qty"           => $item['QuantityOrdered'], // 数量
                "return_qty"    => 0, // 取消数量
                "price"         => $item['ItemPrice']['Amount'], // 售价
                "platform_sku"  => $item['SellerSKU'], // sku
                "name"          => $item['Title'], // 产品名称
                "image_url"         => "", // 图片地址
                "url"           => $this->fillUrl($item['ASIN'], $site), // 商品链接
            ];
            $invoiceCategory = !empty($item['InvoiceData']['BuyerSelectedInvoiceCategory']) ? $item['InvoiceData']['BuyerSelectedInvoiceCategory'] : '';
            $invoiceTitle    = !empty($item['InvoiceData']['InvoiceTitle']) ? $item['InvoiceData']['InvoiceTitle'] : '';
            $invoiceDetail  .= !empty($item['InvoiceData']['InvoiceInformation']) ? $item['InvoiceData']['InvoiceInformation'] : '';
        }
        $platform = $this->getAccountById($ordersTemp->account_id)->platform;
        $address = & $data['ShippingAddress'];
        $order = [
            "order_no"                  => $ordersTemp->order_no,
            "account_id"                => $ordersTemp->account_id,
            "platform_name"             => $platform->name, // 平台名称
            "order_platform_status"     => $data['OrderStatus'], // 订单在平台的状态
            "buyer_gender"              => null, // 客户性别
            "buyer_company"             => null, // 客户公司
            'consignee'                 => $address['Name'], // 收件人
            "buyer_first_name"          => '', // 客户名称
            "buyer_last_name"           => '', // 客户名称
            "buyer_phone"               => !empty($address['Phone']) ? $address['Phone'] : '', // 电话
            "buyer_country"             => '', // 国家
            "buyer_country_code"        => $address['Country'], // 国家编码
            'buyer_province'            => !empty($address['StateOrRegion']) ? $address['StateOrRegion'] : '', // 买家所在省，州
            "buyer_district"            => !empty($address['District']) ? $address['District'] : '', // 区
            "buyer_city"                => $address['City'], // 城市
            "buyer_post_code"           => $address['PostalCode'], // 邮编
            "buyer_address_1"           => $address['AddressLine1'], // 买家收货地址1
            "buyer_address_2"           => !empty($address['AddressLine2']) ? $address['AddressLine2'] : '', // 买家收货地址2
            "buyer_address_3"           => !empty($address['AddressLine3']) ? $address['AddressLine3'] : '', // 买家收货地址3
            "buyer_email"               => $data['BuyerEmail'], // 买家邮箱
            "shipping_price"            => null, // 订单运费
            "order_source_create_time"  => $this->parseTimeToDate($data['PurchaseDate']), // 订单在平台生成的时间
            "payment_method"            => $data['PaymentMethod'], // 支付方式
            "order_price"               => $data['OrderTotal']['Amount'], // 订单金额
            "total_price"               => $data['OrderTotal']['Amount'], // 订单总金额
            "order_pay_time"            => $this->parseTimeToDate($data['LastUpdateDate']), // 订单支付时间
            "currency"                  => $data['OrderTotal']['CurrencyCode'], // 币种
            "invoice_type"              => $invoiceCategory, // 发票种类
            "invoice_title"             => $invoiceTitle, // 发票抬头
            "invoice_detail"            => $invoiceDetail, // 发票详情
            "track_num"                 => $data['FulfillmentChannel'] == 'AFN' ? 'FBA' : '', // 追踪号
            "shipping_method"           => trim($data['ShipmentServiceLevelCategory']), // 运输方式
            "platform_remark"           => '', // 买家备注信息
            "order_detail"              => $info,
        ];
        if($data['FulfillmentChannel'] == 'AFN')
        {
            // FBA 订单
            $order += [
                'is_flag_sent' => Orders::FLAG_SENT_NO_NEED, // 不需要标记
                'order_status' => Orders::ORDER_SUCCESS, // 订单完成
                'send_status'  => Orders::SEND_NO_NEED, // 无需发货
            ];
        }
        else
        {
            // 自发货订单
            $order += [
                "latest_delivery_time" => date('Y-m-d', strtotime($order['order_source_create_time'] . "+{$account->send_day}day")), // 最迟发货时间
            ];
        }
        return OrderService::getInstance()->addOrder($order);
    }

    /**
     * 检测订单 API 接口状态,是否可用
     * @return bool
     * @date 2020/02/20
     * @author longli
     */
    public function checkOrderStatus()
    {
        // @todo
        return true;
    }

    public function markDelivery($orderIds = [])
    {
        foreach($this->getNeedMarkOrders($orderIds) as $order)
        {
            $items = []; // 标记已发货的 sku
            foreach($order->detail as $detail)
            {
                $items[] = [
                    'MerchantOrderItemID' => $detail->item_id,
                    'MerchantFulfillmentItemID' => $detail->item_id,
                    'Quantity' => $detail->qty,
                ];
            }
            $postData = [
                'MessageType' => 'OrderFulfillment',
                'Message' => [
                    'MessageID' => $order->order_id, // 数据库订单 ID
                    'OrderFulfillment' => [
                        'MerchantOrderID' => $order->order_no,
                        'MerchantFulfillmentID' => $order->order_no,
                        'FulfillmentDate' => $this->formatTimeToDate(),
                        'FulfillmentData' => [
                            'CarrierCode' => $order->shipping_method, // USPS
                            'ShippingMethod' => 'Standard', //Standard
                            'ShipperTrackingNumber' => $order->track_num,
                        ],
                        'Item' => $items
                    ]
                ]
            ];
            return $this->getClient()->SubmitFeed('_POST_ORDER_FULFILLMENT_DATA_', $postData);
        }
    }

    /**
     * 通过 asin 码生成 URL
     * @param string $asin 亚马逊 ASIN 码
     * @param string $site 站点国家二字简码
     * @return string
     * @date 2020/03/31
     * @author longli
     */
    public function fillUrl($asin, $site)
    {
        if(empty($asin) || empty($site)) return "";
        $country = [
            'gb' => 'co.uk', // 英国
            'uk' => 'co.uk', // 英国
            'us' => 'com', // 美国
        ];
        $site = strtolower(trim($site));
        if(isset($country[$site])) $site = $country[$site];
        return "https://www.amazon.{$site}/dp/{$asin}";
    }

    /**
     * 获取操作亚马逊的客户端
     * @param int $accountId 账号 id
     * @return MWSClient
     * @date 2020/03/31
     * @author longli
     */
    public function getClient($accountId = 0)
    {
        if(empty($accountId))
            $accountId = $this->getAccountId();
        if(isset(static::$clientInstance[$accountId]))
            return static::$clientInstance[$accountId];
        $account = $this->getAccountById($accountId);
        $config = [
            'Marketplace_Id' => $account->token->marketplace_id,
            'Seller_Id' => $account->token->seller_id,
            'Access_Key_ID' => $account->token->access_key_id,
            'Secret_Access_Key' => $account->token->secret_access_key,
        ];
        // 如果有授权秘钥则添加
        if(!empty($account->token->MWSAuthToken))
            $config['MWSAuthToken'] = $account->token->MWSAuthToken;
        $client = null;
        try
        {
            $client = new MWSClient($config);
            static::$clientInstance[$accountId] = $client; // 缓存客户端
        }
        catch(Exception $e)
        {
            Log::info($e->getMessage()); // 记录异常日志
        }
        return $client;
    }
}